package com.xbongbong.paas.service.stage.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasStageEntity;
import com.xbongbong.paas.domain.entity.StageProcessEntity;
import com.xbongbong.paas.domain.entity.ext.ConditionsEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasFormDataEsModel;
import com.xbongbong.paas.elasticsearch.util.XbbElasticsearchRestTemplate;
import com.xbongbong.paas.enums.ConditionEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.factory.OptionFactory;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.handle.AbstractOptionHandle;
import com.xbongbong.paas.help.FormDataListSearchHelp;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasStageModel;
import com.xbongbong.paas.model.StageProcessModel;
import com.xbongbong.paas.pojo.ButtonPojo;
import com.xbongbong.paas.pojo.LaneCountPojo;
import com.xbongbong.paas.pojo.LaneVersionPojo;
import com.xbongbong.paas.pojo.ShareConditionFormatPojo;
import com.xbongbong.paas.pojo.dto.FormDataListDTO;
import com.xbongbong.paas.pojo.dto.LaneStageCodePageDTO;
import com.xbongbong.paas.pojo.dto.LaneVersionListDTO;
import com.xbongbong.paas.pojo.vo.LaneCountListVO;
import com.xbongbong.paas.pojo.vo.LaneVersionListVO;
import com.xbongbong.paas.pojo.vo.PaasFormDataEsListVO;
import com.xbongbong.paas.pojo.vo.PaasFormLaneDataEsListVO;
import com.xbongbong.paas.pojo.vo.UserFormPermissionVO;
import com.xbongbong.paas.service.ProFormDataService;
import com.xbongbong.paas.service.UserService;
import com.xbongbong.paas.service.stage.StageHandle;
import com.xbongbong.paas.service.stage.StageHandleFactory;
import com.xbongbong.paas.service.stage.StageLaneViewService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.PageHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.businesstage.pojo.StageLaneViewColorWarningPojo;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.enums.PaasStageEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.CustomerStageErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.formdata.pojo.vo.OtherDataListVO;
import com.xbongbong.pro.formexplain.pojo.HandleExplainPojo;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ClueStageEntity;
import com.xbongbong.saas.domain.entity.CustomerStageEntity;
import com.xbongbong.saas.domain.entity.SaleStageEntity;
import com.xbongbong.saas.enums.ListOptionEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.help.SaasHelp;
import com.xbongbong.saas.help.SaasListHelp;
import com.xbongbong.saas.help.StageHelp;
import com.xbongbong.saas.model.ClueStageModel;
import com.xbongbong.saas.model.CustomerStageModel;
import com.xbongbong.saas.model.IndexTypeModel;
import com.xbongbong.saas.model.SaleStageModel;
import com.xbongbong.saas.service.toolbox.help.SaasListDataPermissionHelp;
import com.xbongbong.sys.domain.entity.UserConfigEntity;
import com.xbongbong.sys.enums.UserConfigEnum;
import com.xbongbong.sys.model.UserConfigModel;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.metrics.SumAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;

/**
 * @Author mingliang
 * @Description 泳道视图service
 * @Date 2021/12/6 19:07
 **/
@Service("stageLaneViewService")
public class StageLaneViewServiceImpl implements StageLaneViewService {

    private static final Logger LOG = LoggerFactory.getLogger(StageLaneViewServiceImpl.class);

    @Resource
    private FormDataListSearchHelp formDataListSearchHelp;
    @Resource
    private OptionFactory optionFactory;
    @Resource
    private StageProcessModel stageProcessModel;
    @Resource
    private CustomerStageModel customerStageModel;
    @Resource
    private SaasHelp saasHelp;
    @Resource
    private UserConfigModel userConfigModel;
    @Resource
    private ClueStageModel clueStageModel;
    @Resource
    private SaleStageModel saleStageModel;
    @Resource
    private SaasListHelp saasListHelp;
    @Resource
    private SaasListDataPermissionHelp saasListDataPermissionHelp;
    @Resource
    private PaasFormDataEsModel paasFormDataEsModel;
    @Resource
    private XbbElasticsearchRestTemplate xbbElasticsearchRestTemplate;
    @Resource
    private PaasStageModel paasStageModel;
    @Resource
    private UserService userService;
    @Resource
    private ProFormDataService proFormDataService;
    @Resource
    private IndexTypeModel indexTypeModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private StageHelp stageHelp;
    @Resource
    private StageHandleFactory stageHandleFactory;



    @Override
    public LaneCountListVO laneCustomerStage(LaneStageCodePageDTO laneStageCodePageDTO) throws XbbException {
        LaneCountListVO laneCountListVO = new LaneCountListVO();
        Long stageProcessId = laneStageCodePageDTO.getStageProcessId();
        String corpid = laneStageCodePageDTO.getCorpid();
        Long formId = laneStageCodePageDTO.getFormId();

        Map<String, Object> param = new HashMap<>();
        if (Objects.isNull(stageProcessId)) {
            param.put("corpid", corpid);
            param.put("formId", formId);
            param.put("del", DelEnum.NORMAL.getDel());
            param.put("orderByStr", "  enable desc,priority asc,add_time desc ");
            List<StageProcessEntity> stageProcessEntityList = stageProcessModel.findEntitys(param);
            if (CollectionsUtil.isEmpty(stageProcessEntityList)){
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100071);
            }
            stageProcessId = stageProcessEntityList.get(0).getId();
        }
        param.clear();
        param.put("corpid", corpid);
        param.put("formId", formId);
        param.put("del", DelEnum.NORMAL.getDel());
        param.put("stageProcessId", stageProcessId);
        param.put("enable", 1);
        param.put("orderByStr", "  sort desc ");
        PageHelper pageHelper = PageHelperUtil.getPageHelper(param, customerStageModel, laneStageCodePageDTO.getPage(),laneStageCodePageDTO.getPageSize());
        List<CustomerStageEntity> customerStageEntityList = (List<CustomerStageEntity>) PageHelperUtil.getEntityList(param, pageHelper, customerStageModel);

        //添加阶段数据
        List<LaneCountPojo> laneCountPojoList = new ArrayList<>();
        for (int i = 0; i < customerStageEntityList.size(); i++) {
            CustomerStageEntity temp = customerStageEntityList.get(i);
            LaneCountPojo addPojo = new LaneCountPojo();
            addPojo.setStageTitle(temp.getName());
            addPojo.setStageType(temp.getType());
            addPojo.setStageCode(temp.getCode());
            addPojo.setId(temp.getId());
            laneCountPojoList.add(addPojo);
        }
        //判断需不需要添加其他阶段
        Integer rowsCount = pageHelper.getRowsCount();
        Integer pageSize = pageHelper.getPageSize();
        Integer currentPageNum = pageHelper.getCurrentPageNum();
        int i = currentPageNum * pageSize;
        //当分页数量大于总记录数量或者已加载总数量大于最终总记录添加其他阶段
        if ((rowsCount <= pageSize || i >= rowsCount) && CollectionsUtil.isNotEmpty(laneCountPojoList)) {
            LaneCountPojo otherPojo = new LaneCountPojo();
            otherPojo.setStageTitle(I18nMessageUtil.getMessage(MessageConstant.LANE_CONFIG_OTHER_STAGE));
            otherPojo.setStageCode("-1");
            otherPojo.setStageType(-1);
            laneCountPojoList.add(otherPojo);
        }

        laneCountListVO.setStageCountList(laneCountPojoList);
        laneCountListVO.setPageHelper(pageHelper);
        return laneCountListVO;
    }


    @Override
    public LaneCountListVO getLaneStageInfo(FormDataListDTO formDataListDTO) throws XbbException {
        LaneCountListVO laneCountListVO = new LaneCountListVO();
        Integer saasMark = formDataListDTO.getSaasMark();
        Integer businessType = formDataListDTO.getBusinessType();
        HandleExplainPojo handleExplainPojo = formDataListSearchHelp.handleExplain(formDataListDTO);
        List<FieldAttrEntity> explainList = handleExplainPojo.getExplainList();
        //获得统计的中文名
        String countTitleName = saasHelp.getCountTitleNameByAttr(explainList, formDataListDTO);
        if (StringUtil.isEmpty(countTitleName)){
            laneCountListVO.setShowCount(0);
        }else {
            laneCountListVO.setShowCount(1);
        }
        laneCountListVO.setCountTitleName(countTitleName);
        //添加headList
        if (Objects.equals(SaasMarkEnum.SAAS.getCode(), saasMark)) {
            AbstractOptionHandle abstractOptionHandle = optionFactory.getByBusinessType(businessType, saasMark);
            abstractOptionHandle.setOptionsInExplain(formDataListDTO, explainList, null);
            saasHelp.removeExplainByBusinessType(businessType, explainList);

        }else if (Objects.equals(SaasMarkEnum.PAAS.getCode(), saasMark)){
            explainList.removeIf(e -> Objects.equals(FieldTypeEnum.SEPARATOR.getType(), e.getFieldType())
                    || Objects.equals(FieldTypeEnum.LOCATION.getType(), e.getFieldType())
                    || Objects.equals(FieldTypeEnum.SUB_FORM.getType(), e.getFieldType())
                    || Objects.equals(FieldTypeEnum.IMAGE.getType(), e.getFieldType())
                    || Objects.equals(FieldTypeEnum.UPLOAD.getType(), e.getFieldType())
                    || Objects.equals(e.getAttr(), ListOptionEnum.FLOW.getAttr())//操作按钮跟进记录不需要
            );
            // 添加一行操作列
//            paas无需操作按钮了
//            FieldAttrEntity fieldOption = new FieldAttrEntity();
//            fieldOption.setAttr(ListOptionEnum.OPTION.getAttr());
//            fieldOption.setAttrName(ListOptionEnum.OPTION.getAttrName());
//            fieldOption.setFieldType(FieldTypeEnum.OPTION.getType());
//            explainList.add(0, fieldOption);
        }
//        // 查询此表单是否有排序，有排序的话进行排序
        UserConfigEntity userConfigEntity = userConfigModel.getByUserId(formDataListDTO.getUserId(), formDataListDTO.getCorpid(), UserConfigEnum.LANE_LIST_SORT_FIELD.getAlias() + "_" + formDataListDTO.getAppId() + "_" + formDataListDTO.getFormId());
        if (Objects.nonNull(userConfigEntity)) {
            Map<String, FieldAttrEntity> explainMapByList = ExplainUtil.getExplainMapByList(explainList);
            JSONArray jsonArray = JSONArray.parseArray(userConfigEntity.getConfigValue());
            List<FieldAttrEntity> explainSortList = new ArrayList<>();
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                String attr = jsonObject.getString(StringConstant.ATTR);
                FieldAttrEntity orDefault = explainMapByList.getOrDefault(attr, null);
                if (Objects.nonNull(orDefault)) {
                    explainSortList.add(orDefault);
                }
            }
            explainSortList.forEach(e -> {
                explainList.removeIf(a -> Objects.equals(a.getAttr(), e.getAttr()));
            });
            explainSortList.addAll(explainList);
            laneCountListVO.setHeadList(explainSortList);
        } else {
            laneCountListVO.setHeadList(explainList);
        }

        //是否选中标题
        String laneCountFieldConfigAlias = UserConfigEnum.LANE_SHOW_TITLE.getAlias()+"_" + formDataListDTO.getAppId() + "_" + formDataListDTO.getFormId();
        Map<String, Object> params = new HashMap<>();
        params.put("configAlias", laneCountFieldConfigAlias);
        params.put("userId", formDataListDTO.getUserId());
        params.put("corpid", formDataListDTO.getCorpid());
        params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        List<UserConfigEntity> userConfigList = userConfigModel.list(params);
        if (CollectionsUtil.isEmpty(userConfigList) || (CollectionsUtil.isNotEmpty(userConfigList) && Objects.equals(userConfigList.get(0).getConfigValue(), "1"))) {
            laneCountListVO.setShowTitle(1);
        } else {
            laneCountListVO.setShowTitle(0);
        }
        return laneCountListVO;
    }



    @Override
    public LaneCountListVO laneClueStage(LaneStageCodePageDTO laneStageCodePageDTO) throws XbbException {
        LaneCountListVO laneCountListVO = new LaneCountListVO();
        Long stageProcessId = laneStageCodePageDTO.getStageProcessId();
        String corpid = laneStageCodePageDTO.getCorpid();
        Long formId = laneStageCodePageDTO.getFormId();

        Map<String, Object> param = new HashMap<>();
        if (Objects.isNull(stageProcessId)) {
            param.put("corpid", corpid);
            param.put("formId", formId);
            param.put("del", DelEnum.NORMAL.getDel());
            param.put("orderByStr", "  enable desc,priority asc,add_time desc ");
            List<StageProcessEntity> stageProcessEntityList = stageProcessModel.findEntitys(param);
            if (CollectionsUtil.isEmpty(stageProcessEntityList)){
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100071);
            }
            stageProcessId = stageProcessEntityList.get(0).getId();
        }
        param.clear();
        param.put("corpid", corpid);
        param.put("formId", formId);
        param.put("del", DelEnum.NORMAL.getDel());
        param.put("stageProcessId", stageProcessId);
        param.put("enable", 1);
        param.put("orderByStr", "  sort desc ");
        PageHelper pageHelper = PageHelperUtil.getPageHelper(param, clueStageModel, laneStageCodePageDTO.getPage(),laneStageCodePageDTO.getPageSize());
        List<ClueStageEntity> clueStageEntityList = (List<ClueStageEntity>) PageHelperUtil.getEntityList(param, pageHelper, clueStageModel);
        //添加阶段数据
        List<LaneCountPojo> laneCountPojoList = new ArrayList<>();
        for (int i = 0; i < clueStageEntityList.size(); i++) {
            ClueStageEntity temp = clueStageEntityList.get(i);
            LaneCountPojo addPojo = new LaneCountPojo();
            addPojo.setStageTitle(temp.getName());
            addPojo.setStageType(temp.getType());
            addPojo.setStageCode(temp.getCode());
            addPojo.setId(temp.getId());
            laneCountPojoList.add(addPojo);
        }
        //判断需不需要添加其他阶段
        Integer rowsCount = pageHelper.getRowsCount();
        Integer pageSize = pageHelper.getPageSize();
        Integer currentPageNum = pageHelper.getCurrentPageNum();
        int i = currentPageNum * pageSize;
        //当分页数量大于总记录数量或者已加载总数量大于最终总记录添加其他阶段
        if ((rowsCount <= pageSize || i >= rowsCount) && CollectionsUtil.isNotEmpty(laneCountPojoList)) {
            LaneCountPojo otherPojo = new LaneCountPojo();
            otherPojo.setStageTitle(I18nMessageUtil.getMessage(MessageConstant.LANE_CONFIG_OTHER_STAGE));
            otherPojo.setStageCode("-1");
            otherPojo.setStageType(-1);
            laneCountPojoList.add(otherPojo);
        }
        laneCountListVO.setStageCountList(laneCountPojoList);
        laneCountListVO.setPageHelper(pageHelper);
        return laneCountListVO;
    }

    @Override
    public LaneCountListVO laneOpportunityStage(LaneStageCodePageDTO laneStageCodePageDTO) throws XbbException {
        LaneCountListVO laneCountListVO = new LaneCountListVO();
        Long stageProcessId = laneStageCodePageDTO.getStageProcessId();
        String corpid = laneStageCodePageDTO.getCorpid();
        Long formId = laneStageCodePageDTO.getFormId();

        Map<String, Object> param = new HashMap<>();
        if (Objects.isNull(stageProcessId)) {
            param.put("corpid", corpid);
            param.put("formId", formId);
            param.put("del", DelEnum.NORMAL.getDel());
            param.put("orderByStr", "  enable desc,priority asc,add_time desc ");
            List<StageProcessEntity> stageProcessEntityList = stageProcessModel.findEntitys(param);
            if (CollectionsUtil.isEmpty(stageProcessEntityList)){
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100071);
            }
            stageProcessId = stageProcessEntityList.get(0).getId();
        }
        param.clear();
        param.put("corpid", corpid);
        param.put("formId", formId);
        param.put("del", DelEnum.NORMAL.getDel());
        param.put("stageProcessId", stageProcessId);
        param.put("enable", 1);
        param.put("orderByStr", "  sort desc ");
        PageHelper pageHelper = PageHelperUtil.getPageHelper(param, saleStageModel,laneStageCodePageDTO.getPage(), laneStageCodePageDTO.getPageSize());
        List<SaleStageEntity> saleStageEntityList = (List<SaleStageEntity>) PageHelperUtil.getEntityList(param, pageHelper, saleStageModel);
        //添加阶段数据
        List<LaneCountPojo> laneCountPojoList = new ArrayList<>();
        for (int i = 0; i < saleStageEntityList.size(); i++) {
            SaleStageEntity temp = saleStageEntityList.get(i);
            LaneCountPojo addPojo = new LaneCountPojo();
            addPojo.setStageTitle(temp.getName());
            addPojo.setStageType(temp.getType());
            addPojo.setStageCode(temp.getCode());
            addPojo.setId(temp.getId());
            laneCountPojoList.add(addPojo);
        }
        //判断需不需要添加其他阶段
//        军昊说商机不需要其他阶段
//        Integer rowsCount = pageHelper.getRowsCount();
//        Integer pageSize = pageHelper.getPageSize();
//        Integer currentPageNum = pageHelper.getCurrentPageNum();
//        int i = currentPageNum * pageSize;
//        //当分页数量大于总记录数量或者已加载总数量大于最终总记录添加其他阶段
//        if ((rowsCount <= pageSize || i >= rowsCount) && CollectionsUtil.isNotEmpty(laneCountPojoList)) {
//            LaneCountPojo otherPojo = new LaneCountPojo();
//            otherPojo.setStageTitle(I18nMessageUtil.getMessage(MessageConstant.LANE_CONFIG_OTHER_STAGE));
//            otherPojo.setStageCode("-1");
//            otherPojo.setStageType(-1);
//            laneCountPojoList.add(otherPojo);
//        }
        laneCountListVO.setStageCountList(laneCountPojoList);
        laneCountListVO.setPageHelper(pageHelper);
        return laneCountListVO;
    }

    @Override
    public LaneCountListVO lanePaasStage(LaneStageCodePageDTO laneStageCodePageDTO) throws XbbException {
        LaneCountListVO laneCountListVO = new LaneCountListVO();
        Long stageProcessId = laneStageCodePageDTO.getStageProcessId();
        String corpid = laneStageCodePageDTO.getCorpid();
        Long formId = laneStageCodePageDTO.getFormId();

        Map<String, Object> param = new HashMap<>();
        if (Objects.isNull(stageProcessId)) {
            param.put("corpid", corpid);
            param.put("formId", formId);
            param.put("del", DelEnum.NORMAL.getDel());
            param.put("orderByStr", "  enable desc,priority asc,add_time desc ");
            List<StageProcessEntity> stageProcessEntityList = stageProcessModel.findEntitys(param);
            if (CollectionsUtil.isEmpty(stageProcessEntityList)){
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100071);
            }
            stageProcessId = stageProcessEntityList.get(0).getId();
        }
        param.clear();
        param.put("corpid", corpid);
        param.put("formId", formId);
        param.put("del", DelEnum.NORMAL.getDel());
        param.put("stageProcessId", stageProcessId);
        param.put("enable", 1);
        param.put("orderByStr", "  sort desc ");
        PageHelper pageHelper = PageHelperUtil.getPageHelper(param, paasStageModel,laneStageCodePageDTO.getPage(), laneStageCodePageDTO.getPageSize());
        List<PaasStageEntity> paasStageEntityList = (List<PaasStageEntity>) PageHelperUtil.getEntityList(param, pageHelper, paasStageModel);
        //添加阶段数据
        List<LaneCountPojo> laneCountPojoList = new ArrayList<>();
        for (int i = 0; i < paasStageEntityList.size(); i++) {
            PaasStageEntity temp = paasStageEntityList.get(i);
            LaneCountPojo addPojo = new LaneCountPojo();
            addPojo.setStageTitle(temp.getName());
            addPojo.setStageType(temp.getType());
            addPojo.setStageCode(temp.getCode());
            addPojo.setId(temp.getId());
            laneCountPojoList.add(addPojo);
        }
        //判断需不需要添加其他阶段
        Integer rowsCount = pageHelper.getRowsCount();
        Integer pageSize = pageHelper.getPageSize();
        Integer currentPageNum = pageHelper.getCurrentPageNum();
        int i = currentPageNum * pageSize;
        //当分页数量大于总记录数量或者已加载总数量大于最终总记录添加其他阶段
        if ((rowsCount <= pageSize || i >= rowsCount) && CollectionsUtil.isNotEmpty(laneCountPojoList)) {
            LaneCountPojo otherPojo = new LaneCountPojo();
            otherPojo.setStageTitle(I18nMessageUtil.getMessage(MessageConstant.LANE_CONFIG_OTHER_STAGE));
            otherPojo.setStageCode("-1");
            otherPojo.setStageType(-1);
            laneCountPojoList.add(otherPojo);
        }
        laneCountListVO.setStageCountList(laneCountPojoList);
        laneCountListVO.setPageHelper(pageHelper);
        return laneCountListVO;
    }

    @Override
    public LaneVersionListVO laneVersionList(LaneVersionListDTO laneVersionListDTO) throws XbbException {
        LaneVersionListVO laneVersionListVO = new LaneVersionListVO();
        Map<String, Object> param = new HashMap<>();
        param.put("corpid", laneVersionListDTO.getCorpid());
        param.put("formId", laneVersionListDTO.getFormId());
        param.put("del", DelEnum.NORMAL.getDel());
        param.put("orderByStr", "  enable desc,priority asc,add_time desc");
        param.put("isArchive", laneVersionListDTO.getArchive());
        List<StageProcessEntity> stageProcessEntityList = stageProcessModel.findEntitys(param);
        List<LaneVersionPojo> versionPojoList = new ArrayList<>();
        if (CollectionsUtil.isEmpty(stageProcessEntityList)) {
            laneVersionListVO.setVersionList(versionPojoList);
            return laneVersionListVO;
        }
        for (StageProcessEntity temp : stageProcessEntityList) {
            LaneVersionPojo pojo = new LaneVersionPojo();
            pojo.setStageProcessId(temp.getId());
            pojo.setName(temp.getVersionName());
            pojo.setVersionId(temp.getVersionId());
            pojo.setEnable(temp.getEnable());
            pojo.setPriority(temp.getPriority());
            versionPojoList.add(pojo);
        }
        laneVersionListVO.setVersionList(versionPojoList);
        return laneVersionListVO;
    }

    @Override
    public PaasFormLaneDataEsListVO laneViewList(FormDataListDTO formDataListDTO) throws XbbException {
        PaasFormLaneDataEsListVO paasFormLaneDataEsListVO = new PaasFormLaneDataEsListVO();
        try {
            //  拼装阶段code进搜索条件,-1为其他阶段
            String stageCode = formDataListDTO.getStageCode();
            //评分区间筛选
            saasListHelp.handleScoreRangeCondition(formDataListDTO.getCorpid(), formDataListDTO.getFormId(), formDataListDTO.getBusinessType(), formDataListDTO.getConditions());


            Integer subBusinessType = formDataListDTO.getSubBusinessType();
            List<ConditionsEntityExt> conditionList = formDataListDTO.getConditions();
            conditionList.addAll(saasListHelp.packageConditionBySubBusinessType(subBusinessType, formDataListDTO.getCorpid(), formDataListDTO.getUserId(), formDataListDTO.getStatusFilter()));
            // 数据权限
            List<ConditionsEntityExt> permissionConditions = saasListDataPermissionHelp.listDataPermission(false, conditionList, formDataListDTO.getLoginUser(), formDataListDTO.getBusinessType(), formDataListDTO.getSubBusinessType());
            formDataListDTO.setConditions(conditionList);
            Long stageProcessId = formDataListDTO.getStageProcessId();
            if (Objects.isNull(stageProcessId)){
                throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238053);
            }
            //如果是老数据或者其他阶段数据，则查询stageProcessId为空或者stageProcessId相等的数据
            StageProcessEntity stageProcessEntity = stageProcessModel.getByKey(stageProcessId, formDataListDTO.getCorpid());
            if ((Objects.nonNull(stageProcessEntity) && Objects.equals(stageProcessEntity.getOldTransferVersion(), 1)) || Objects.equals(stageCode, "-1")) {
                formDataListDTO.setLegacyDataFlag(true);
            }

            formDataListDTO.setConditions(conditionList);

            // 封装数据权限
            ShareConditionFormatPojo shareConditionFormatPojo = new ShareConditionFormatPojo();
            shareConditionFormatPojo.setPermissionConditions(permissionConditions);
            formDataListDTO.setSharePermission(shareConditionFormatPojo);
            // 数据相关拼装
            HandleExplainPojo handleExplainPojo = formDataListSearchHelp.handleExplain(formDataListDTO);
            List<FieldAttrEntity> explainList = handleExplainPojo.getExplainList();
            PaasFormEntityExt form = handleExplainPojo.getForm();
            // 获取需要查询的字段，不再查询自定义子表单字段；
            List<String> fieldList = formDataListDTO.getFieldList();
            if (CollectionsUtil.isNotEmpty(fieldList)) {
                fieldList.addAll(handleExplainPojo.getFieldList());
                formDataListDTO.setFieldList(fieldList);
            } else {
                formDataListDTO.setFieldList(handleExplainPojo.getFieldList());
            }

            //查询排序字段
            String laneDefaultSortConfigAlias = UserConfigEnum.LANE_DEFAULT_SORT_FIELD.getAlias()+"_" + formDataListDTO.getAppId() + "_" + formDataListDTO.getFormId();
            Map<String,Object> params=new HashMap<>();
            params.put("configAlias", laneDefaultSortConfigAlias);
            params.put("userId", formDataListDTO.getUserId());
            params.put("corpid", formDataListDTO.getCorpid());
            params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            List<UserConfigEntity> defaultSort = userConfigModel.list(params);
            Map<String,String> sortMap = new HashMap<>();
            if (CollectionsUtil.isNotEmpty(defaultSort)) {
                JSONObject jsonObject = JSONObject.parseObject(defaultSort.get(0).getConfigValue());
                sortMap.put("field",jsonObject.getString("sortAttr"));
                sortMap.put("sort",jsonObject.getString("sortType"));
            }else{
                sortMap.put("field","updateTime");
                sortMap.put("sort","desc");
            }


            if (Objects.equals(SaasMarkEnum.SAAS.getCode(), formDataListDTO.getSaasMark())) {
                formDataListDTO.setSortMap(sortMap);
                String stageCodeAttr = null;
                if (Objects.equals(formDataListDTO.getBusinessType(), XbbRefTypeEnum.CONTRACT.getCode())) {
                    for (FieldAttrEntity temp : explainList) {
                        if (Objects.equals(temp.getFieldType(), FieldTypeEnum.STAGE_THRUSTER.getType())) {
                            stageCodeAttr = temp.getAttr();
                            break;
                        }
                    }
                } else {
                    stageCodeAttr = PaasStageEnum.getStageCodeAttr(formDataListDTO.getBusinessType());
                }
                if (Objects.equals(stageCode, "-1")) {
                    conditionList.add(new ConditionsEntityExt(stageCodeAttr, "", FieldTypeEnum.TEXT.getType(), ConditionEnum.EMPTY.getSymbol(),new ArrayList<>()));
                } else {
                    conditionList.add(new ConditionsEntityExt(stageCodeAttr, "", FieldTypeEnum.TEXT.getType(), ConditionEnum.EQUAL.getSymbol(), Collections.singletonList(stageCode)));
                }
            } else if (Objects.equals(SaasMarkEnum.PAAS.getCode(), formDataListDTO.getSaasMark())) {
                // 添加一行操作列
                FieldAttrEntity fieldOption = new FieldAttrEntity();
                fieldOption.setAttr(ListOptionEnum.OPTION.getAttr());
                fieldOption.setAttrName("查看");
                fieldOption.setFieldType(FieldTypeEnum.OPTION.getType());
                explainList.add(0, fieldOption);

                String stageAttr = null;
                for (FieldAttrEntity temp : explainList) {
                    if (Objects.equals(temp.getFieldType(), FieldTypeEnum.STAGE_THRUSTER.getType())) {
                        stageAttr = temp.getAttr();
                        break;
                    }
                }
                if (StringUtil.isNotEmpty(stageAttr)){
                    if (Objects.equals(stageCode, "-1")) {
                        conditionList.add(new ConditionsEntityExt(stageAttr, "", FieldTypeEnum.TEXT.getType(), ConditionEnum.EMPTY.getSymbol(),new ArrayList<>()));
                    }else {
                        conditionList.add(new ConditionsEntityExt(stageAttr, "", FieldTypeEnum.TEXT.getType(), ConditionEnum.EQUAL.getSymbol(), Collections.singletonList(stageCode)));
                    }
                }
            }


            //数据查询
            IndexTypeEnum indexTypeEnum = indexTypeModel.getIndexType(formDataListDTO.getCorpid(), formDataListDTO.getBusinessType(), formDataListDTO.getSaasMark());
            PaasFormDataEsListVO paasFormDataEsListVO = paasFormDataEsModel.list(formDataListDTO, indexTypeEnum);
            List<PaasFormDataEntityExt> paasFormDataESList = paasFormDataEsListVO.getPaasFormDataESList();
            if (CollectionsUtil.isEmpty(paasFormDataESList)) {
                paasFormLaneDataEsListVO.setPageHelper(paasFormDataEsListVO.getPageHelper());
                paasFormLaneDataEsListVO.setDataList(new JSONArray());
                paasFormLaneDataEsListVO.setSum(new BigDecimal(0));
                return paasFormLaneDataEsListVO;
            }
            paasFormDataEsListVO.setUpdateTime(handleExplainPojo.getUpdateTime());
            paasFormDataEsListVO.setForm(form);
            paasFormDataEsListVO.setHeadList(explainList);
            paasFormDataEsListVO.setExplainMap(formDataListDTO.getExplainMap());

            StageLaneViewColorWarningPojo stageLaneViewColorWarningPojo = isShowStageWarningColor(formDataListDTO, paasFormDataEsListVO);

            formDataListSearchHelp.webDataAnalysisByLane(formDataListDTO, paasFormDataEsListVO);
            formDataListSearchHelp.setButtons(formDataListDTO, paasFormDataEsListVO);

            //获得操作列，展示列，统计标题
            JSONObject showFieldAttrList = saasHelp.getShowFieldAttrList(formDataListDTO,explainList, form.getSummaryList());
            List<FieldAttrEntity> showList = showFieldAttrList.getObject("showList", List.class);
            List<FieldAttrEntity> showOperationList = showFieldAttrList.getObject("showOperationList", List.class);
            String countField = showFieldAttrList.getString("countField");
            Map<String, FieldAttrEntity> showOperationMap = new HashMap<>();
            if (CollectionsUtil.isNotEmpty(showOperationList)){
                showOperationList.forEach(e -> {
                    showOperationMap.put(e.getAttr(), e);
                });
            }
            stageLaneViewColorWarningPojo.judgeIsShow4ShowList(showList);
            boolean isShowStageWarningColor = stageLaneViewColorWarningPojo.isShowStageWarningColor();
            Map<Long, Long> dataId2NowIntoStageTimeMap = stageLaneViewColorWarningPojo.getDataId2NowIntoStageTimeMap();
            PaasStageEntity stageEntity = stageLaneViewColorWarningPojo.getStageEntity();


            // 客户的电话需要重新解析...
            if (Objects.equals(formDataListDTO.getBusinessType(),XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())){
                List<Long> idIn = new ArrayList<>();
                paasFormDataESList.forEach(e->{
                    idIn.add(e.getDataId());
                });
                formDataListDTO.setIdIn(idIn);
                OtherDataListVO otherDataListVO = proFormDataService.otherDataList(formDataListDTO);
                List<PaasFormDataEntityExt> formDataESList = otherDataListVO.getPaasFormDataESList();
                if (CollectionsUtil.isNotEmpty(formDataESList)){
                    Map<Long,Object> map = new HashMap<>(20);
                    formDataESList.forEach(e->{
                        JSONObject data = e.getData();
                        if (Objects.nonNull(data)){
                            map.put(e.getDataId(),data.get(ListOptionEnum.CALL.getAttr()));
                        }
                    });
                    paasFormDataESList.forEach(e->{
                        if (map.containsKey(e.getDataId())){
                            e.getData().put(ListOptionEnum.CALL.getAttr(),map.get(e.getDataId()));
                        }
                    });
                }
            }

            //数据列解析与排序
            JSONArray jsonArray = new JSONArray();
            for (PaasFormDataEntityExt temp : paasFormDataEsListVO.getPaasFormDataESList()) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("id", temp.getId());
                jsonObject.put("appId", temp.getAppId());
                jsonObject.put("menuId", temp.getMenuId());
                jsonObject.put("formId", temp.getFormId());
                jsonObject.put("businessType", formDataListDTO.getBusinessType());
                jsonObject.put("saasMark",formDataListDTO.getSaasMark());
                JSONObject tagData = temp.getTagData();
                JSONArray tagArray = Objects.isNull(tagData)?null:tagData.getJSONArray("text_1Tag");
                JSONObject data = temp.getData();
                JSONArray rowJsonArray = new JSONArray();
                Set<JSONObject> optionJsonArray = new HashSet<>();
                for (FieldAttrEntity fieldAttrEntity : showList) {
                    String attr = fieldAttrEntity.getAttr();
                    String attrName = fieldAttrEntity.getAttrName();
                    Integer fieldType = fieldAttrEntity.getFieldType();
                    for (JSONObject.Entry<String, Object> entry : data.entrySet()) {
                        String key = entry.getKey();
                        if (showOperationMap.containsKey(key)) {
                            FieldAttrEntity fieldAttr = showOperationMap.get(key);
                            JSONObject option = new JSONObject();
                            option.put("attrName", fieldAttr.getAttrName());
                            option.put("fieldType", fieldAttr.getFieldType());
                            if (Objects.equals(SaasMarkEnum.SAAS.getCode(),formDataListDTO.getSaasMark())){
                                option.put("value", entry.getValue());
                            }else if (Objects.equals(SaasMarkEnum.PAAS.getCode(),formDataListDTO.getSaasMark())){
                                JSONObject parseObject = JSONObject.parseObject(entry.getValue().toString());
                                option.put("value", parseObject.get("value"));
                            }
                            option.put("attr", fieldAttr.getAttr());

                            if (Objects.equals(ListOptionEnum.CALL.getAttr(), key)) {
                                jsonObject.put("phoneInfo", option);
                            } else {
                                optionJsonArray.add(option);
                            }
                        } else if (Objects.equals(attr, key)) {
                            JSONObject object = new JSONObject();
                            object.put("attr", attr);
                            object.put("attrName", attrName);
                            object.put("fieldType", fieldType);
                            object.put("value", entry.getValue());
                            object.put("explain", fieldAttrEntity);

                            //是否显示预警颜色功能、并判断当前轮询的attr是否为该显示字段
                            if (isShowStageWarningColor && Objects.equals(attr, stageLaneViewColorWarningPojo.getNowIntoStageTimeAttr())) {
                                Long intoTime = dataId2NowIntoStageTimeMap.get(temp.getDataId());
                                //判断是否超时
                                if (stageHelp.isTimeout(stageEntity.getStayLimitTime(), stageEntity.getStayLimitTimeUnit(), intoTime, DateTimeUtil.getInt())) {
                                    Map<String, String> style = new HashMap<>();
                                    style.put("color", stageEntity.getStageWarningColor());
                                    object.put("style", style);
                                }
                            }

                            if (Objects.nonNull(tagArray) && "text_1Tag".contains(key)) {
                                object.put("text_1Tag", tagArray);
                            }
                            rowJsonArray.add(object);
                        }
                    }
                }
                jsonObject.put("data", rowJsonArray);
                //paas不需要操作按钮了
                if (SaasMarkEnum.SAAS.getCode().equals(formDataListDTO.getSaasMark())){
                    jsonObject.put("option", optionJsonArray);
                }
                jsonArray.add(jsonObject);
            }
            BigDecimal sum = new BigDecimal(0);
            if (StringUtil.isNotEmpty(countField)){
                SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                SearchRequest searchRequest = paasFormDataEsModel.getSearchRequest(formDataListDTO, indexTypeEnum, sourceBuilder, boolQueryBuilder);
                boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, indexTypeEnum.getType()));
                //设置查询条件
                sourceBuilder.query(boolQueryBuilder);
                sourceBuilder.size(0);
                SumAggregationBuilder sumAggregationBuilder = AggregationBuilders.sum(countField).field("data." + countField);
                sourceBuilder.aggregation(sumAggregationBuilder);
                searchRequest.source(sourceBuilder);
                JSONObject aggJson = xbbElasticsearchRestTemplate.getAggResponseJson(searchRequest);

                JSONObject aggregations = aggJson.getJSONObject("aggregations");
                JSONObject object = aggregations.getJSONObject(countField);
                sum = object.getBigDecimal("value");
            }
            paasFormLaneDataEsListVO.setPageHelper(paasFormDataEsListVO.getPageHelper());
            paasFormLaneDataEsListVO.setDataList(jsonArray);
            paasFormLaneDataEsListVO.setSum(sum);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("泳道视图分页查询失败：{}",e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return paasFormLaneDataEsListVO;
    }

    @Override
    public PaasFormLaneDataEsListVO topButton(FormDataListDTO formDataListDTO) throws XbbException {
        PaasFormLaneDataEsListVO paasFormLaneDataEsListVO = new PaasFormLaneDataEsListVO();
        try {
            PaasFormEntityExt form = formDataListSearchHelp.getForm(formDataListDTO);
            Integer saasMark = formDataListDTO.getSaasMark();
            //获取顶部
            if (Objects.equals(SaasMarkEnum.SAAS.getCode(), saasMark)) {
                List<ButtonPojo> topButtonList = new ArrayList<>();
                List<ButtonPojo> batchButtonList = new ArrayList<>();
                PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formDataListDTO.getFormId(), formDataListDTO.getCorpid());
                List<FieldAttrEntity> fieldAttrEntityList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
                formDataListSearchHelp.getTopAndButtonList(formDataListDTO, formDataListDTO.getCorpid(), formDataListDTO.getSubBusinessType(), topButtonList, batchButtonList, form, fieldAttrEntityList);
                paasFormLaneDataEsListVO.setTopPermissions(topButtonList);
            } else if (Objects.equals(SaasMarkEnum.PAAS.getCode(), saasMark)) {
                UserFormPermissionVO userFormPermissionVO = userService.getUserFormPermissionInternal(formDataListDTO.getCorpid(), formDataListDTO.getUserId(), formDataListDTO.getAppId(), formDataListDTO.getMenuId());
                PaasFormDataEsListVO formDataListVO = new PaasFormDataEsListVO();
                formDataListVO.setHeadList(new ArrayList<>());
                formDataListVO.setPaasFormDataESList(new ArrayList<>());
                formDataListVO.setForm(form);
                formDataListSearchHelp.setListButtonPermission(formDataListDTO, formDataListVO, userFormPermissionVO, formDataListDTO.getDel());
                paasFormLaneDataEsListVO.setTopPermissions(formDataListVO.getTopPermissions());
            }
        } catch (XbbException e) {
            LOG.error("泳道视图获得顶部按钮失败：{}", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }

        return paasFormLaneDataEsListVO;
    }

    /**
     * 判断泳道图是否需要显示颜色预警信息
     *
     * @param formDataListDTO           列表入参
     * @param paasFormDataEsListVO      数据列表
     * @return StageLaneViewColorWarningPojo
     */
    private StageLaneViewColorWarningPojo isShowStageWarningColor(FormDataListDTO formDataListDTO, PaasFormDataEsListVO paasFormDataEsListVO) {
        StageLaneViewColorWarningPojo stageLaneViewColorWarningPojo = new StageLaneViewColorWarningPojo();

        // 判断是否阶段推进器相关业务
        if (!XbbRefTypeEnum.isSupportStageProcess(formDataListDTO.getSaasMark(), formDataListDTO.getBusinessType())) {
            return stageLaneViewColorWarningPojo;
        }
        FieldAttrEntity nowIntoStageTimeEntity = ExplainUtil.getFieldWithFieldType(paasFormDataEsListVO.getHeadList(), FieldTypeEnum.NOW_INTO_STAGE_TIME.getType());
        if (Objects.isNull(nowIntoStageTimeEntity) || Objects.equals(nowIntoStageTimeEntity.getIsOpen(), 0)) {
            return stageLaneViewColorWarningPojo;
        }
        // 判断客户白名单
        if (!stageHelp.isSupportStageStayTime(formDataListDTO.getCorpid())) {
            return stageLaneViewColorWarningPojo;
        }
        StageHandle stageHandle = stageHandleFactory.getStageHandle(formDataListDTO.getSaasMark(), formDataListDTO.getBusinessType());
        PaasStageEntity stageEntity = stageHandle.getByCode(formDataListDTO.getCorpid(), formDataListDTO.getFormId(), formDataListDTO.getStageCode());
        if (Objects.isNull(stageEntity) || !Objects.equals(stageEntity.getEnableStageWarningColor(), BasicConstant.ONE)) {
            return stageLaneViewColorWarningPojo;
        }

        // 因为下面 webDataAnalysisByLane 方法把时间转换了，所以这里保存dataId到时间戳的映射
        Map<Long, Long> dataId2NowIntoStageTimeMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (PaasFormDataEntityExt formDataEntity : paasFormDataEsListVO.getPaasFormDataESList()) {
            Long nowIntoStageTime = formDataEntity.getData().getLong(nowIntoStageTimeEntity.getAttr());
            if (Objects.nonNull(nowIntoStageTime)) {
                dataId2NowIntoStageTimeMap.put(formDataEntity.getDataId(), nowIntoStageTime);
            }
        }

        return new StageLaneViewColorWarningPojo(true, dataId2NowIntoStageTimeMap, nowIntoStageTimeEntity.getAttr(), stageEntity);
    }

}
